package com.hua.api.modules.order.service.impl;


import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import com.hua.api.core.constants.Status;
import com.hua.api.core.framework.util.exception.ApiError;
import com.hua.api.core.properties.SysProperties;
import com.hua.api.core.util.StringUtil;
import com.hua.api.core.util.ValidationUtil;
import com.hua.api.modules.finance.service.UserAccountService;
import com.hua.api.modules.home.service.ActiveMqService;
import com.hua.api.modules.order.dao.OrderBidDao;
import com.hua.api.modules.order.dao.OrderInfoDao;
import com.hua.api.modules.order.dao.ShopInfoDao;
import com.hua.api.modules.order.domain.*;
import com.hua.api.modules.order.repository.OrderBidItemRepository;
import com.hua.api.modules.order.service.OrderBidService;
import com.hua.api.modules.order.service.dto.OrderBidDto;
import com.hua.api.modules.order.service.dto.OrderBidQueryCriteria;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@SuppressWarnings("all")
@Slf4j
@Service
@RequiredArgsConstructor
public class OrderBidServiceImpl implements OrderBidService {


    private final OrderBidDao orderBidDao;

    private final OrderInfoDao orderInfoDao;

    private final ShopInfoDao shopInfoDao;

    private final OrderBidItemRepository orderBidItemRepository;

    private final UserAccountService userAccountService;

    private final ActiveMqService activeMqService;

    private final SysProperties sysProperties;

    /**
     * 直接转单
     * */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void change(Integer shopId, OrderBidDto dto, Integer userId) {
        log.info("OrderBidServiceImpl.change shopId={},dealPrice={},orderId={}",shopId,dto.getDealPrice(),dto.getOrderId());
        if(StringUtil.isEmptys(shopId,dto.getOrderId(),dto.getDealPrice())){
            throw ApiError.Type.LOGIC_ERROR.toException("缺少必要参数!");
        }
        OrderInfo order = orderBidDao.getObject(OrderInfo.class,dto.getOrderId());
        ValidationUtil.requireNotNull(order,"订单信息不存在！");
        // 订单状态判断
        Status.OrderStatus status = Status.OrderStatus.fromValue(order.getStatus());
        if(status!= Status.OrderStatus.yijiedan){
            throw ApiError.Type.LOGIC_ERROR.toException(order.getId()+"订单状态异常 status:"+order.getStatus());
        }
        // 订单配送状态判断
        Status.LogisticsStatus logisticsStatus = Status.LogisticsStatus.fromValue(order.getLogisticsStatus());
        if(logisticsStatus!=Status.LogisticsStatus.daipeisong){
            throw ApiError.Type.LOGIC_ERROR.toException(order.getId()+"订单的配送状态异常，转单失败 getLogisticsStatus:"+order.getLogisticsStatus());
        }

        List<OrderBid> list = orderBidDao.queryOrderBidUseOrderId(dto.getOrderId());
        if(list.size()>0){
            throw ApiError.Type.LOGIC_ERROR.toException(order.getId()+"订单转单信息已存在!  status:"+list.size());
        }

        order.setUtime(new Date());
        order.setStatus(Status.OrderStatus.zhuadan.getValue());
        orderBidDao.updateObject(order);

        // 生成竞价订单表
        OrderBid orderBid = new OrderBid();
        orderBid.setOrderId(order.getId());
        orderBid.setCreatedTime(new Date());
        orderBid.setDistance(0);
        orderBid.setBidPrice(dto.getDealPrice()); //参考价格

        orderBid.setAutoDealPrice(dto.getDealPrice());
        orderBid.setDealPrice(dto.getDealPrice()); //成交价
        orderBid.setState(Status.BidStatus.biding.getValue());
        orderBidDao.saveObject(orderBid);

        //
        OrderBidItem obi = new OrderBidItem();
        obi.setOrderBidId(orderBid.getId());
        obi.setDistance(0);
        obi.setShopId(shopId);
        obi.setCreatedTime(new Date());
        obi.setBidPrice(dto.getDealPrice());
        obi.setModifyTime(3);
        obi.setBidTime(new Date());
        obi.setState(Status.BidItemsStatus.biding.getValue());
        orderBidDao.saveObject(obi);


        String operateDesc = "订单转固定店铺！shopId:"+shopId;
        activeMqService.onOrderInfoLogger(null,null,dto.getOrderId(),Status.OrderEvent.orderBill.getValue(),Status.OrderEvent.orderBill.getName(),operateDesc);
        // 自动选中竞价单
        chooseWinner(obi.getId());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void orderBidCreate(OrderBidDto dto, Integer userId) {
        log.info("生成转单数据 orderId = {},转单价格 = {} , 距离 = {}",dto.getOrderId(),dto.getBidPrice(),dto.getDistance());
        ValidationUtil.requireNotNull(dto.getOrderId(),"订单信息不存在！");
        ValidationUtil.requireNotNull(dto.getBidPrice(),"缺少转单价格！");
        OrderInfo order = orderBidDao.getObject(OrderInfo.class,dto.getOrderId());
        ValidationUtil.requireNotNull(order,"订单信息不存在！");
        Status.OrderStatus status = Status.OrderStatus.fromValue(order.getStatus());
        if(status!= Status.OrderStatus.yijiedan){
            throw ApiError.Type.LOGIC_ERROR.toException(order.getId()+"订单状态异常 status:"+order.getStatus());
        }
        Status.LogisticsStatus logisticsStatus = Status.LogisticsStatus.fromValue(order.getLogisticsStatus());
        if(logisticsStatus!=Status.LogisticsStatus.daipeisong){
            throw ApiError.Type.LOGIC_ERROR.toException(order.getId()+"订单的配送状态异常，转单失败 getLogisticsStatus:"+order.getLogisticsStatus());
        }
        List<OrderBid> list = orderBidDao.queryOrderBidUseOrderId(dto.getOrderId());
        if(list.size()>0){
            throw ApiError.Type.LOGIC_ERROR.toException(order.getId()+"订单正在转单中  status:"+list.size());
        }
        if(StringUtil.isEmptys(order.getLatitude(),order.getLongitude()) || order.getLatitude() ==0d || order.getLongitude()==0d){
            throw ApiError.Type.LOGIC_ERROR.toException(order.getId()+"订单的经纬度信息缺失，无法转单！");
        }

        Integer distance = StringUtil.isEmpty(dto.getDistance())?3000:dto.getDistance();
        List<Map<String,Object>>  blist = orderBidDao.queryShopInfoWithDistance(order.getLongitude(),order.getLatitude(),dto.getDistance(),order.getShopId(),dto.getShopIds());
        if(blist.size()==0){
            throw ApiError.Type.LOGIC_ERROR.toException(order.getId()+"收货地址附近无可用的店铺 status:"+order.getStatus());
        }

        OrderBid orderBid = new OrderBid();
        orderBid.setOrderId(order.getId());
        orderBid.setCreatedTime(new Date());
        orderBid.setDistance(distance);
        orderBid.setBidPrice(dto.getBidPrice()); //参考价格
        orderBid.setAutoDealPrice(dto.getBidPrice());
        orderBid.setDealPrice(0d); //成交价
        orderBid.setState(Status.BidStatus.biding.getValue());

        orderBidDao.saveObject(orderBid);
        List<OrderBidItem> item = new ArrayList<>();
        // 用户消息推送用户id
        Set<Integer> userIds = new HashSet<>();
        // 手机号发送短信消息
        Set<String> phoneNumbers = new HashSet<>();

        for(Map<String,Object> map : blist){

            OrderBidItem obi = new OrderBidItem();
            obi.setCreatedTime(new Date());
            Integer shopId =  NumberUtil.parseInt(StringUtil.dealNull(map.get("id"))); // NumberUtil.parseInt(map.get("id")); // 店铺id
            Double distanceD =  NumberUtil.parseDouble(StringUtil.dealNull(map.get("distance")));
            Integer uid = NumberUtil.parseInt(StringUtil.dealNull(map.get("user_id")));
            String phoneNumber = StringUtil.dealNull(map.get("phone_number"));
            Integer mi =  distanceD.intValue(); // 距离
            obi.setShopId(shopId);
            obi.setDistance(mi);
            obi.setState(Status.BidItemsStatus.unread.getValue());
            obi.setOrderBidId(orderBid.getId());
            obi.setModifyTime(3);
            orderBidDao.saveObject(obi);
            item.add(obi);
            phoneNumbers.add(phoneNumber);
            userIds.add(uid);
        }

        // 订单标记未转单中
        order.setUtime(new Date());
        order.setStatus(Status.OrderStatus.zhuadan.getValue());
        orderBidDao.updateObject(order);
        String context = "您有新的订单可报价接单，单号"+order.getOrderNo()+",请登录系统查看！";
        // 短信消息推送
        activeMqService.onSmsSender(phoneNumbers,context);


        Status.UserMessage userMessage = Status.UserMessage.orderBid;
        // 消息通知
        String title=userMessage.getName();
        String type = userMessage.getValue();
        activeMqService.onUserMesssage(userIds,title,context,type,1,Status.mp3_order_bid);

    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void orderBidCancel(Integer bidId, Integer userId) {
        log.info("orderBidCancel 取消转单数据 bidId = {}", bidId);
        OrderBid bid = orderBidDao.getObject(OrderBid.class,bidId);
        ValidationUtil.requireNotNull(bid,"竞价单不存在！");
        OrderInfo order = orderInfoDao.getObject(OrderInfo.class,bid.getOrderId());
        ValidationUtil.requireNotNull(order,"订单数据不存在！！");

        Status.BidStatus bidStatus = Status.BidStatus.fromValue(bid.getState());
        if(bidStatus != Status.BidStatus.biding){
            throw ApiError.Type.LOGIC_ERROR.toException("竞价单状态异常 "+bidStatus.getName());
        }
        Status.OrderStatus orderStatus = Status.OrderStatus.fromValue(order.getStatus());
        // 直接修改状态
        bid.setState(Status.BidStatus.yiquxiao.getValue());
        orderBidDao.updateObject(bid);
        // 回归订单状态
        if(orderStatus == Status.OrderStatus.zhuadan){
            order.setStatus(Status.OrderStatus.yijiedan.getValue());
            orderInfoDao.updateObject(order);
        }



        String operateDesc = "订单取消竞价单！";
        activeMqService.onOrderInfoLogger(null,null,bid.getOrderId(),Status.OrderEvent.orderBill.getValue(),Status.OrderEvent.orderBill.getName(),operateDesc);

    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void chooseWinner(Integer itemId) {
        log.info("选中订单成交店铺数据 itemId={}",itemId);
        OrderBidItem obi = orderBidDao.getObject(OrderBidItem.class,itemId);
        ValidationUtil.requireNotNull(obi,"竞价数据不存在！");
        OrderBid orderBid = orderBidDao.getObject(OrderBid.class,obi.getOrderBidId());
        ValidationUtil.requireNotNull(obi,"竞价单不存在！");
        Status.BidItemsStatus bidItemsStatus = Status.BidItemsStatus.fromValue(obi.getState());

        if(bidItemsStatus != Status.BidItemsStatus.biding){
            throw ApiError.Type.LOGIC_ERROR.toException("非报价中状态! ");
        }


        OrderInfo orderInfo = orderBidDao.getObject(OrderInfo.class,orderBid.getOrderId());
        ValidationUtil.requireNotNull(orderInfo,"订单数据不存在！");

        Status.OrderStatus orderStatus = Status.OrderStatus.fromValue(orderInfo.getStatus());
        if(orderStatus != Status.OrderStatus.zhuadan){
            throw ApiError.Type.LOGIC_ERROR.toException("订单状态异常! ");
        }

        Status.BidStatus bidStatus = Status.BidStatus.fromValue(orderBid.getState());
        if(bidStatus!=Status.BidStatus.biding){
            throw ApiError.Type.LOGIC_ERROR.toException("状态异常！");
        }

        List<OrderBidItem> list = orderBidItemRepository.queryByOrderBidId(obi.getOrderBidId());

        // 用户消息推送用户id
        Set<Integer> userIds = new HashSet<>();
        // 手机号发送短信消息
        Set<String> phoneNumbers = new HashSet<>();
        Status.UserMessage userMessage = Status.UserMessage.orderBid;
        for(OrderBidItem o : list ){
            if(StringUtil.equals(o.getId(),itemId)){

                Integer originShopId = orderInfo.getShopId();
                // 转单用户店铺扣除金额
                userAccountService.onUserAccountSubUseShopId(originShopId,o.getBidPrice(),"order_info","订单转单金额扣除 orderBidId="+obi.getId());

                log.info("选中订单成交店铺数据 itemId={}",itemId);
                ShopInfo shopInfo = shopInfoDao.getObject(ShopInfo.class,obi.getShopId());
                ValidationUtil.requireNotNull(shopInfo,"店铺信息不存在！");
                orderInfo.setShopId(obi.getShopId());
                orderInfo.setWmPoiName(shopInfo.getShopName());
                orderInfo.setWmPoiPhone(shopInfo.getPhoneNumber());
                orderInfo.setWmPoiAddress(shopInfo.getShopAddress());
                orderInfo.setRealMoneyYuan(obi.getBidPrice());
                orderInfo.setStatus(Status.OrderStatus.yijiedan.getValue());
                // 结算费用
                orderBidDao.updateObject(orderInfo);

                orderBid.setDealPrice(obi.getBidPrice());
                orderBid.setWinnerItemId(itemId);
                orderBid.setUpdateTime(new Date());
                orderBid.setState(Status.BidStatus.dealing.getValue());
                orderBidDao.updateObject(orderBid);
                // 竞价成功
                obi.setState(Status.BidItemsStatus.success.getValue());
                orderBidDao.updateObject(obi);


                Set<Integer> successUser = new HashSet<>();

                // 消息通知
                successUser.add(shopInfo.getUserId());
                String context = "您的订单报价接单成功，单号"+orderInfo.getOrderNo()+",请登录系统查看！";
                activeMqService.onUserMesssage(successUser,userMessage.getName(),context,userMessage.getValue(),0,Status.mp3_order_bid);


                String operateDesc = "订单接单成功 接单店铺shopId:"+shopInfo.getId()+"shopName:"+shopInfo.getShopName();
                activeMqService.onOrderInfoLogger(null,null,orderInfo.getId(),Status.OrderEvent.orderBill.getValue(),Status.OrderEvent.orderBill.getName(),operateDesc);

            }else{
                Status.BidItemsStatus bidStatus1 = Status.BidItemsStatus.fromValue(o.getState());
                if(bidStatus1 == Status.BidItemsStatus.biding){
                    userIds.add(o.getUserId());
                }
                log.info("取消报价数据 itemId={}",o.getId());
                o.setState(Status.BidItemsStatus.bidfail.getValue());
                orderBidDao.updateObject(o);
            }
        }

        String context = "您的订单报价接单失败，单号"+orderInfo.getOrderNo()+"！";
        activeMqService.onUserMesssage(userIds,userMessage.getName(),context,userMessage.getValue(),0,Status.mp3_order_bid);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void bidPrice(OrderBidQueryCriteria criteria,Integer userId){
        log.info("bidPrice 店铺报价 getBidPrice={} ,orderBidItemId = {}",criteria.getBidPrice(),criteria.getOrderBidItemId());
        if(StringUtil.isEmptys(criteria.getBidPrice(),criteria.getOrderBidItemId())){
            throw ApiError.Type.LOGIC_ERROR.toException("缺少必要参数！");
        }
        OrderBidItem bidItem = orderBidDao.getObject(OrderBidItem.class,criteria.getOrderBidItemId());
        ValidationUtil.requireNotNull(bidItem,"竞价数据不存在 "+criteria.getOrderBidItemId());
        OrderBid orderBid = orderBidDao.getObject(OrderBid.class,bidItem.getOrderBidId());
        ValidationUtil.requireNotNull(orderBid,"竞价单不存在！ "+bidItem.getOrderBidId());
        Status.BidStatus bidStatus = Status.BidStatus.fromValue(orderBid.getState());
        if(bidStatus != Status.BidStatus.biding){
            throw ApiError.Type.LOGIC_ERROR.toException("转单状态异常！");
        }

        ShopInfo shopInfo = orderBidDao.getObject(ShopInfo.class,bidItem.getShopId());
        ValidationUtil.requireNotNull(shopInfo,"店铺信息不存在 "+criteria.getOrderBidItemId());
        if(!StringUtil.equals(userId,shopInfo.getUserId())){
            throw ApiError.Type.LOGIC_ERROR.toException("无权限报价！");
        }
        if(criteria.getBidPrice()<orderBid.getBidPrice()){
            throw ApiError.Type.LOGIC_ERROR.toException("无效的报价！报价价格:"+criteria.getBidPrice()+",转单价格："+orderBid.getBidPrice());
        }

        Status.BidItemsStatus itemsStatus = Status.BidItemsStatus.fromValue(bidItem.getState());


        if(bidItem.getModifyTime()!=null && bidItem.getModifyTime()==0){
            throw ApiError.Type.LOGIC_ERROR.toException("您的出价次数已经用完！");
        }
        // 待报价 ，已报价 已取消 状态下可以重新报价
        if(itemsStatus == Status.BidItemsStatus.unread || itemsStatus == Status.BidItemsStatus.unbind || itemsStatus == Status.BidItemsStatus.bidcancel || itemsStatus == Status.BidItemsStatus.biding){
            bidItem.setState(Status.BidItemsStatus.biding.getValue());
            bidItem.setBidTime(new Date());
            Integer mt = bidItem.getModifyTime() == null? 2 : bidItem.getModifyTime()-1;
            bidItem.setModifyTime(mt);
            bidItem.setBidPrice(criteria.getBidPrice());
            orderBidDao.updateObject(bidItem);
        }else{
            throw ApiError.Type.LOGIC_ERROR.toException("竞价单状态异常！");
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void jiedan(OrderBidQueryCriteria criteria, Integer userId) {

        if(StringUtil.isEmptys(criteria.getOrderBidItemId())){
            throw ApiError.Type.LOGIC_ERROR.toException("缺少必要参数！");
        }
        OrderBidItem bidItem = orderBidDao.getObject(OrderBidItem.class,criteria.getOrderBidItemId());
        ValidationUtil.requireNotNull(bidItem,"竞价数据不存在 "+criteria.getOrderBidItemId());

        OrderBid orderBid = orderBidDao.getObject(OrderBid.class,bidItem.getOrderBidId());
        ValidationUtil.requireNotNull(orderBid,"竞价单不存在！ "+bidItem.getOrderBidId());
        Status.BidStatus bidStatus = Status.BidStatus.fromValue(orderBid.getState());
        if(bidStatus != Status.BidStatus.biding){
            throw ApiError.Type.LOGIC_ERROR.toException("转单状态异常！");
        }

        Status.BidItemsStatus itemsStatus = Status.BidItemsStatus.fromValue(bidItem.getState());

        if(itemsStatus!=Status.BidItemsStatus.unread && itemsStatus!=Status.BidItemsStatus.unbind && itemsStatus!=Status.BidItemsStatus.bidcancel ){
            throw ApiError.Type.LOGIC_ERROR.toException("竞价单状态异常！！");
        }

        bidItem.setState(Status.BidItemsStatus.biding.getValue());
        bidItem.setBidTime(new Date());
        bidItem.setBidPrice(orderBid.getBidPrice());
        orderBidDao.updateObject(bidItem);

        // 直接接单
        chooseWinner(bidItem.getId());
    }


    // 接单用户取消接单
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void jiedanCancel(Integer bidItemId, Integer userId) {
        log.info("接单订单取消接单 bidItemId={},userId={}",bidItemId,userId);
        OrderBidItem item = orderBidDao.getObject(OrderBidItem.class,bidItemId);
        ValidationUtil.requireNotNull(item,"OrderBidItem竞价数据不存在 bidItemId:"+bidItemId);
        OrderBid orderBid = orderBidDao.getObject(OrderBid.class,item.getOrderBidId());
        ValidationUtil.requireNotNull(item,"OrderBid数据不存在 getOrderBidId:"+item.getOrderBidId());
        OrderInfo orderInfo = orderInfoDao.getObject(OrderInfo.class,orderBid.getOrderId());
        ValidationUtil.requireNotNull(orderInfo,"OrderInfo数据不存在 getOrderId:"+orderBid.getOrderId());
        ShopInfo shopInfo = shopInfoDao.getObject(ShopInfo.class,orderInfo.getShopId());
        ValidationUtil.requireNotNull(shopInfo,"OrderInfo数据不存在 getShopId:"+orderInfo.getShopId());
        ShopInfoChannel shopInfoChannel = orderInfoDao.getObject(ShopInfoChannel.class,sysProperties.shopInfoChannel);
        ValidationUtil.requireNotNull(shopInfo,"shopInfoChannel数据不存在 getShopId:"+sysProperties.shopInfoChannel);

        // 订单配送状态
        Status.LogisticsStatus  logisticsStatus = Status.LogisticsStatus.fromValue(orderInfo.getLogisticsStatus());
        // 订单状态
        Status.OrderStatus orderStatus = Status.OrderStatus.fromValue(orderInfo.getStatus());

        if(logisticsStatus != Status.LogisticsStatus.daipeisong){
            throw ApiError.Type.LOGIC_ERROR.toException("订单配送状态异常，无法取消！logisticsStatus="+orderInfo.getLogisticsStatus());
        }

        if(orderStatus != Status.OrderStatus.yijiedan){
            throw ApiError.Type.LOGIC_ERROR.toException("订单状态异常，无法取消！orderStatus="+orderInfo.getStatus());
        }

        if(!StringUtil.equals(shopInfo.getUserId(),userId)){
            throw ApiError.Type.LOGIC_ERROR.toException("无操作权限！");
        }

        // 0 : 修改 OrderBidItem 状态取消
        item.setState(Status.BidItemsStatus.bidcancel.getValue());

        // 1: 修改 OrderBid 状态取消
        orderBid.setState(Status.BidStatus.yiquxiao.getValue());
        orderBid.setWinnerItemId(null);
        orderBid.setDealPrice(0d);

        // 2: 修改订单所属店铺为官方店铺。
        orderInfo.setWmPoiAddress(shopInfoChannel.getAddress());
        orderInfo.setWmPoiName(shopInfoChannel.getName());
        orderInfo.setWmPoiPhone(shopInfoChannel.getPhone());
        orderInfo.setShopCode(shopInfoChannel.getShopCode());
        orderInfo.setShopId(shopInfoChannel.getShopId());

        orderBidDao.updateObject(item);
        orderBidDao.updateObject(orderBid);
        orderBidDao.updateObject(orderInfo);

        // 3: 是否需要扣除金额
        Double money = fineMoney(orderInfo,item);
        if(money>0){
            userAccountService.onUserAccountSubUseShopId(shopInfo.getId(),money,"order_info","取消接单扣除金额! 订单号 ["+orderInfo.getId()+"]");
        }

        // 4: 记录日志
        String operateDesc = "接单店铺取消接单！扣除取单金额："+money+"元！";
        activeMqService.onOrderInfoLogger(userId,null,orderInfo.getId(),Status.OrderEvent.orderInfo.getValue(),Status.OrderEvent.orderInfo.getName(),operateDesc);

    }

    @Override
    public Double getFineMoney(Integer bidItemId) {
        log.info("getFineMoney bidItemId={}",bidItemId);
        OrderBidItem item = orderBidDao.getObject(OrderBidItem.class,bidItemId);
        ValidationUtil.requireNotNull(item,"OrderBidItem竞价数据不存在 bidItemId:"+bidItemId);
        OrderBid orderBid = orderBidDao.getObject(OrderBid.class,item.getOrderBidId());
        ValidationUtil.requireNotNull(item,"OrderBid数据不存在 getOrderBidId:"+item.getOrderBidId());
        OrderInfo orderInfo = orderInfoDao.getObject(OrderInfo.class,orderBid.getOrderId());
        ValidationUtil.requireNotNull(orderInfo,"OrderInfo数据不存在 getOrderId:"+orderBid.getOrderId());
        return fineMoney(orderInfo,item);
    }

    /**
     * 取消订单，需要罚款金额
     *
     * 当日即时单花店接单之后超出2小时取消订单  设置为：每次罚款30元   点击取消按钮时需要弹窗通知花店。
     * 客户预定次日订单 花店接单之后超过8小时 取消订单  设置为：每次罚款30元 点击取消按钮时需要弹窗通知花店。
     * */
    private Double fineMoney(OrderInfo orderInfo,OrderBidItem item){
        // 接单时间
        Date bidTime = item.getBidTime();
        Date beginDate = orderInfo.getDeliveryTime();
        // Date lastDate = orderInfo.getLastDeliveryTime();
        // 距离最早配送时间
        String jiedanDate = DateUtil.format(bidTime,"yyyy-MM-dd");
        String deliveryDate = DateUtil.format(beginDate,"yyyy-MM-dd");
        long minutes = DateUtil.between(bidTime,new Date(),DateUnit.MINUTE);
        // 接单时间与配送时间同一天
        if(StringUtil.equals(jiedanDate,deliveryDate)){
            if(minutes>120){
                return  30d;
            }
        }else {
            // 接单时间与配送时间不是同一天
            if(minutes>480) {
                return 30d;
            }
        }
        return 0d;
    }



    @Transactional(rollbackFor = Exception.class)
    @Override
    public void bidCancel(OrderBidQueryCriteria criteria, Integer userId) {

        if(StringUtil.isEmptys(criteria.getOrderBidItemId())){
            throw ApiError.Type.LOGIC_ERROR.toException("缺少必要参数！");
        }
        OrderBidItem bidItem = orderBidDao.getObject(OrderBidItem.class,criteria.getOrderBidItemId());
        ValidationUtil.requireNotNull(bidItem,"竞价数据不存在 "+criteria.getOrderBidItemId());
        OrderBid orderBid = orderBidDao.getObject(OrderBid.class,bidItem.getOrderBidId());
        ValidationUtil.requireNotNull(orderBid,"竞价单不存在！ "+bidItem.getOrderBidId());

        Status.BidStatus bidStatus = Status.BidStatus.fromValue(orderBid.getState());
        if(bidStatus != Status.BidStatus.biding){
            throw ApiError.Type.LOGIC_ERROR.toException("转单状态异常！");
        }

        ShopInfo shopInfo = orderBidDao.getObject(ShopInfo.class,bidItem.getShopId());
        ValidationUtil.requireNotNull(shopInfo,"店铺信息不存在 "+criteria.getOrderBidItemId());

        if(!StringUtil.equals(userId,shopInfo.getUserId())){
            throw ApiError.Type.LOGIC_ERROR.toException("无操作权限！");
        }


        Status.BidItemsStatus itemsStatus = Status.BidItemsStatus.fromValue(bidItem.getState());
        if(itemsStatus!=Status.BidItemsStatus.biding){
            throw ApiError.Type.LOGIC_ERROR.toException("竞价单状态异常,无法取消！");
        }

        bidItem.setState(Status.BidItemsStatus.bidcancel.getValue());
        bidItem.setBidTime(new Date());
        bidItem.setBidPrice(criteria.getBidPrice());
        orderBidDao.updateObject(bidItem);

    }

    /**
     * 竞价单完成
     * */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void bidFinish(Integer orderId) {
        log.info("转单订单完成 orderId={}");
        List<OrderBid> list = orderBidDao.queryOrderOnBidFinish(orderId);

        for(OrderBid ob:list){
            OrderBidItem obi = orderBidDao.getObject(OrderBidItem.class,ob.getWinnerItemId());
            if(obi!=null){
                obi.setState(Status.BidItemsStatus.done.getValue());
                orderBidDao.updateObject(obi);
                log.info("OrderBidItem id ={},已完成",obi.getId());
            }
            ob.setState(Status.BidStatus.done.getValue());
            orderBidDao.updateObject(obi);
            log.info("OrderBid id ={},已完成",ob.getId());

        }

    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void setOrderBidFinishJob() {
        //
        Date beginDate = DateUtil.offsetDay(new Date(),-30).toJdkDate();
        Date endDate = DateUtil.offsetHour(new Date(),-1).toJdkDate();
        List<OrderBid> list = orderBidDao.querNeedFinishOrderBid(beginDate, endDate);
        log.info("setOrderBidFinishJob 转单订单完成 size={}",list.size());
        for(OrderBid ob:list){
            OrderBidItem obi = orderBidDao.getObject(OrderBidItem.class,ob.getWinnerItemId());
            if(obi!=null){
                obi.setState(Status.BidItemsStatus.done.getValue());
                orderBidDao.updateObject(obi);
                log.info("OrderBidItem id ={},已完成",obi.getId());
            }
            ob.setState(Status.BidStatus.done.getValue());
            orderBidDao.updateObject(obi);
            log.info("OrderBid id ={},已完成",ob.getId());
        }

    }


}
